import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:hc_bot_pro/chat/controller_bot.dart';
import 'package:hc_bot_pro/chat/controller_broadcast.dart';
import 'package:hc_bot_pro/chat/state.dart';
import 'package:hc_bot_pro/common/model/chat/purpose.dart';
import 'package:hc_bot_pro/common/service/chat/chat.dart';
import 'package:hc_bot_pro/common/service/chat/purpose.dart';

import '../common/model/chat/chat.dart';
import '../common/speech/service.dart';

class ChatController extends FullLifeCycleController with FullLifeCycleMixin {
  final state = ChatState();
  //滚动控制器
  final tableViewController = ScrollController();

  ChatController();

  _initData() async {
    try {
      await EasyLoading.show();
      await setUpBot();
      setUpBroadcastReceiver();

      await clearConversation();
      await Future.delayed(5.seconds);

      await sayHi();
    } catch (e) {
      print(e);
    } finally {
      EasyLoading.dismiss();
      update(["chat"]);
    }
  }

  // @override
  // void onInit() {
  //   super.onInit();
  // }

  @override
  void onReady() {
    super.onReady();
    _initData();
  }

  @override
  void onClose() {
    super.onClose();
    tableViewController.dispose();
    Get.find<HCAISpeechService>().dispose();
    debugPrint("onClose");
  }

  @override
  void onResumed() {
    debugPrint("onResumed");
  }

  @override
  void onPaused() {
    debugPrint("onPaused");
  }

  @override
  void onInactive() {
    debugPrint("onInactive");
  }

  @override
  void onDetached() {
    debugPrint("onDetached");
  }

  @override
  void onHidden() {
    debugPrint("onHidden");
  }
}

extension Basic on ChatController {
  Future say({required String phase, bool isCompleted = true}) async {
    debugPrint("say:$phase");
    if (isInteractionEnable) {
      updateRobotStatus(HCAIBotStatus.speaking);
    }
    await Get.find<HCAISpeechService>().tts.say(phase, isCompleted: isCompleted);
  }

  Future clearConversation() async {
    await state.reset();
    update(["chat"]);
  }

  Future endConversation() async {
    await Get.find<HCAISpeechService>().tts.pause();
    await Get.find<HCAISpeechService>().asr.sleep();
    Get.find<ChatService>().cancel();
    await clearConversation();
  }

  Future addChat(ChatModel chat) async {
    state.chatList.add(chat);
    update(["chat"]);
    await Future.delayed(300.milliseconds);
    tableViewController.jumpTo(tableViewController.position.maxScrollExtent);
  }

  bool get isInteractionEnable => !Get.find<HCAISpeechService>().asr.isSleep;
}

extension ConversationEX on ChatController {
  Future sayHi() async {
    if (state.chatList.isNotEmpty) return;
    final welcome = ChatModel.fromOther(state.welcomeMessage);
    addChat(welcome);
    await say(phase: state.welcomeMessage);
  }

  Future tipQR() async {
    await Future.delayed(1.seconds);
    final tip = ChatModel.fromOther(state.qrTip);
    addChat(tip);
    await say(phase: state.qrTip);
  }

  Future ask(String question) async {
    debugPrint("ask:$question");
    if (question.isEmpty || state.isThinking) return;

    try {
      //
      await Get.find<HCAISpeechService>().asr.pause();

      //
      final askChat = ChatModel.fromMe(question);
      await addChat(askChat);

      updateRobotStatus(HCAIBotStatus.thinking);
      Purpose? purpose = await extractPurpose(question);
      if (purpose != null) {
        tipQR();
        return;
      }
      await answer(question);
    } catch (e) {
      final errDesc = "err in ask ${e.toString()}";
      EasyLoading.showError(errDesc, duration: 10.seconds);

      if (!state.chatList.last.isMe) {
        state.chatList.removeLast();
      }

      updateRobotStatus(HCAIBotStatus.listening);
    } finally {
      await Get.find<HCAISpeechService>().asr.resume();
    }
  }

  Future answer(String question) async {
    var answerChat = ChatModel.fromOther("");
    await addChat(answerChat);
    try {
      await Get.find<ChatService>().answer(
        question: question,
        conversationID: state.conversationID,
      );
    } catch (e) {
      print(e);
    }
  }

  Future<Purpose?> extractPurpose(String question) async {
    Purpose? purpose;
    purpose = await Get.find<PurposeService>().ask(
      message: question,
      conversationID: state.conversationID,
    );
    await purpose?.handle();
    return purpose;
  }
}
